import { useMessage } from '@/hooks/message'
import { isArray } from '@/utils/is'
import moment from 'moment'

/**
 * @description 获取localStorage
 * @param {String} key Storage名称
 * @returns {String}
 */
export function localGet(key: string) {
  const value = window.localStorage.getItem(key)
  try {
    return JSON.parse(window.localStorage.getItem(key) as string)
  } catch (error) {
    return value
  }
}

/**
 * @description 存储localStorage
 * @param {String} key Storage名称
 * @param {*} value Storage值
 * @returns {void}
 */
export function localSet(key: string, value: any) {
  window.localStorage.setItem(key, JSON.stringify(value))
}

/**
 * @description 清除localStorage
 * @param {String} key Storage名称
 * @returns {void}
 */
export function localRemove(key: string) {
  window.localStorage.removeItem(key)
}

/**
 * @description 清除所有localStorage
 * @returns {void}
 */
export function localClear() {
  window.localStorage.clear()
}

/**
 * @description 判断数据类型
 * @param {*} val 需要判断类型的数据
 * @returns {String}
 */
export function isType(val: any) {
  if (val === null) return 'null'
  if (typeof val !== 'object') return typeof val
  else return Object.prototype.toString.call(val).slice(8, -1).toLocaleLowerCase()
}

/**
 * @description 生成唯一 uuid
 * @returns {String}
 */
export function generateUUID() {
  let uuid = ''
  for (let i = 0; i < 32; i++) {
    const random = (Math.random() * 16) | 0
    if (i === 8 || i === 12 || i === 16 || i === 20) uuid += '-'
    uuid += (i === 12 ? 4 : i === 16 ? (random & 3) | 8 : random).toString(16)
  }
  return uuid
}

/**
 * 判断两个对象是否相同
 * @param {Object} a 要比较的对象一
 * @param {Object} b 要比较的对象二
 * @returns {Boolean} 相同返回 true，反之 false
 */
export function isObjectValueEqual(a: { [key: string]: any }, b: { [key: string]: any }) {
  if (!a || !b) return false
  const aProps = Object.getOwnPropertyNames(a)
  const bProps = Object.getOwnPropertyNames(b)
  if (aProps.length != bProps.length) return false
  for (let i = 0; i < aProps.length; i++) {
    const propName = aProps[i]
    const propA = a[propName]
    const propB = b[propName]
    if (!b.hasOwnProperty(propName)) return false
    if (propA instanceof Object) {
      if (!isObjectValueEqual(propA, propB)) return false
    } else if (propA !== propB) {
      return false
    }
  }
  return true
}

/**
 * @description 生成随机数
 * @param {Number} min 最小值
 * @param {Number} max 最大值
 * @returns {Number}
 */
export function randomNum(min: number, max: number): number {
  const num = Math.floor(Math.random() * (min - max) + max)
  return num
}

/**
 * @description 获取当前时间对应的提示语
 * @returns {String}
 */
export function getTimeState() {
  const timeNow = new Date()
  const hours = timeNow.getHours()
  if (hours >= 6 && hours <= 10) return `早上好 ⛅`
  if (hours >= 10 && hours <= 14) return `中午好 🌞`
  if (hours >= 14 && hours <= 18) return `下午好 🌞`
  if (hours >= 18 && hours <= 24) return `晚上好 🌛`
  if (hours >= 0 && hours <= 6) return `凌晨好 🌛`
}

/**
 * @description 使用递归扁平化菜单，方便添加动态路由
 * @param {Array} menuList 菜单列表
 * @returns {Array}
 */
export function getFlatMenuList(menuList: Menu.MenuOptions[]): Menu.MenuOptions[] {
  const newMenuList: Menu.MenuOptions[] = JSON.parse(JSON.stringify(menuList))
  return newMenuList.flatMap((item) => [
    item,
    ...(item.children ? getFlatMenuList(item.children) : []),
  ])
}

/**
 * @description 使用递归过滤出需要渲染在左侧菜单的列表 (需剔除 isHide == true 的菜单)
 * @param {Array} menuList 菜单列表
 * @returns {Array}
 * */
export function getShowMenuList(menuList: Menu.MenuOptions[]) {
  const newMenuList: Menu.MenuOptions[] = JSON.parse(JSON.stringify(menuList))
  return newMenuList.filter((item) => {
    item.children?.length && (item.children = getShowMenuList(item.children))
    return !item.meta?.isHide
  })
}

/**
 * @description 使用递归找出所有面包屑存储到 pinia/vuex 中
 * @param {Array} menuList 菜单列表
 * @param {Array} parent 父级菜单
 * @param {Object} result 处理后的结果
 * @returns {Object}
 */
export const getAllBreadcrumbList = (
  menuList: Menu.MenuOptions[],
  parent = [],
  result: { [key: string]: any } = {}
) => {
  for (const item of menuList) {
    result[item.path] = [...parent, item]
    if (item.children) getAllBreadcrumbList(item.children, result[item.path], result)
  }
  return result
}

/**
 * @description 使用递归处理路由菜单 path，生成一维数组 (第一版本地路由鉴权会用到，该函数暂未使用)
 * @param {Array} menuList 所有菜单列表
 * @param {Array} menuPathArr 菜单地址的一维数组 ['**','**']
 * @returns {Array}
 */
export function getMenuListPath(
  menuList: Menu.MenuOptions[],
  menuPathArr: string[] = []
): string[] {
  for (const item of menuList) {
    if (typeof item === 'object' && item.path) menuPathArr.push(item.path)
    if (item.children?.length) getMenuListPath(item.children, menuPathArr)
  }
  return menuPathArr
}

/**
 * @description 递归查询当前 path 所对应的菜单对象 (该函数暂未使用)
 * @param {Array} menuList 菜单列表
 * @param {String} path 当前访问地址
 * @returns {Object | null}
 */
export function findMenuByPath(
  menuList: Menu.MenuOptions[],
  path: string
): Menu.MenuOptions | null {
  for (const item of menuList) {
    if (item.path === path) return item
    if (item.children) {
      const res = findMenuByPath(item.children, path)
      if (res) return res
    }
  }
  return null
}

/**
 * @description 使用递归过滤需要缓存的菜单 name (该函数暂未使用)
 * @param {Array} menuList 所有菜单列表
 * @param {Array} keepAliveNameArr 缓存的菜单 name ['**','**']
 * @returns {Array}
 * */
export function getKeepAliveRouterName(
  menuList: Menu.MenuOptions[],
  keepAliveNameArr: string[] = []
) {
  menuList.forEach((item) => {
    item.meta.isKeepAlive && item.name && keepAliveNameArr.push(item.name)
    item.children?.length && getKeepAliveRouterName(item.children, keepAliveNameArr)
  })
  return keepAliveNameArr
}

/**
 * @description 格式化表格单元格默认值 (el-table-column)
 * @param {Number} row 行
 * @param {Number} col 列
 * @param {*} callValue 当前单元格值
 * @returns {String}
 * */
export function formatTableColumn(row: number, col: number, callValue: any) {
  // 如果当前值为数组，使用 / 拼接（根据需求自定义）
  if (isArray(callValue)) return callValue.length ? callValue.join(' / ') : '--'
  return callValue ?? '--'
}

/**
 * @description 处理值无数据情况
 * @param {*} callValue 需要处理的值
 * @returns {String}
 * */
export function formatValue(callValue: any) {
  // 如果当前值为数组，使用 / 拼接（根据需求自定义）
  if (isArray(callValue)) return callValue.length ? callValue.join(' / ') : '--'
  return callValue ?? '--'
}

/**
 * @description 处理 prop 为多级嵌套的情况，返回的数据 (列如: prop: user.name)
 * @param {Object} row 当前行数据
 * @param {String} prop 当前 prop
 * @returns {*}
 * */
export function handleRowAccordingToProp(row: { [key: string]: any }, prop: string) {
  if (!prop.includes('.')) return row[prop] ?? '--'
  prop.split('.').forEach((item) => (row = row[item] ?? '--'))
  return row
}

/**
 * @description 处理 prop，当 prop 为多级嵌套时 ==> 返回最后一级 prop
 * @param {String} prop 当前 prop
 * @returns {String}
 * */
export function handleProp(prop: string) {
  const propArr = prop.split('.')
  if (propArr.length == 1) return prop
  return propArr[propArr.length - 1]
}

/**
 * @description 递归查找 callValue 对应的 enum 值
 * */
export function findItemNested(enumData: any, callValue: any, value: string, children: string) {
  return enumData.reduce((accumulator: any, current: any) => {
    if (accumulator) return accumulator
    if (current[value] === callValue) return current
    if (current[children]) return findItemNested(current[children], callValue, value, children)
  }, null)
}

export const getNowDate = () => {
  //获取当前时间
  const date = new Date()
  const sign2 = ':'
  const year = date.getFullYear() // 年
  let month: any = date.getMonth() + 1 // 月
  let day: any = date.getDate() // 日
  let hour: any = date.getHours() // 时
  let minutes: any = date.getMinutes() // 分
  let seconds: any = date.getSeconds() //秒
  const weekArr = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期天']
  const week = weekArr[date.getDay()]
  // 给一位数的数据前面加 “0”
  if (month >= 1 && month <= 9) {
    month = '0' + month
  }
  if (day >= 0 && day <= 9) {
    day = '0' + day
  }
  if (hour >= 0 && hour <= 9) {
    hour = '0' + hour
  }
  if (minutes >= 0 && minutes <= 9) {
    minutes = '0' + minutes
  }
  if (seconds >= 0 && seconds <= 9) {
    seconds = '0' + seconds
  }
  return year + '-' + month + '-' + day + ' ' + hour + sign2 + minutes + sign2 + seconds
}

// 文件名后缀
export function getFileType(fileName) {
  const splitStr = fileName.split('.')
  return `.${splitStr[splitStr.length - 1]}`
}

// 将日期格式转换成时间戳
export function timeToTimestamp(time) {
  return new Date(time).getTime()
}

// 将时间戳转换成日期格式
export function timestampToTime(timestamp) {
  const d = new Date((timestamp + '').length == 10 ? timestamp * 1000 : timestamp) // 时间戳为10位需*1000，时间戳为13位的话不需乘1000【(timestamp+'')表示：转换成字符串型】
  const yyyy = d.getFullYear() + '-' // 年
  const MM = (d.getMonth() + 1 < 10 ? '0' + (d.getMonth() + 1) : d.getMonth() + 1) + '-' // 月 (js中获取月份date.getMonth()获取的是0-11，所以要+1)
  const dd = d.getDate() < 10 ? '0' + d.getDate() : d.getDate() // 日
  const h = (d.getHours() < 10 ? '0' + d.getHours() : d.getHours()) + ':' // 小时
  const m = (d.getMinutes() < 10 ? '0' + d.getMinutes() : d.getMinutes()) + ':' // 分钟
  const s = d.getSeconds() < 10 ? '0' + d.getSeconds() : d.getSeconds() // 秒
  return yyyy + MM + dd + ' ' + h + m + s
}

/**
 * @method 截取时间只展示年月日
 */
//
export function formatterTime(value) {
  return /\d{4}-\d{1,2}-\d{1,2}/g.exec(value)
}
export function startOfDay(isoDateStr: string): string {
  console.log(isoDateStr)
  if (!isoDateStr) return ''
  return isoDateStr.substring(0, 10)
}

/**
 * @method 金额千分符,会在整数后添加两个0
 */
//

export function formatterMoney(value) {
  if (Number(value) >= 0) {
    return Number(value)
      .toFixed(2)

      .replace(/(\d)(?=(\d{3})+\.)/g, ($0, $1) => {
        return $1 + ','
      })

      .replace(/\.$/, '')
  }
}

// utils.js
export const download = (res, type, filename) => {
  // 创建blob对象，利用Blob解析流数据
  const blob = new Blob([res], {
    // 如何后端没返回下载文件类型，则需要手动设置：type: 'application/pdf;charset=UTF-8' 表示下载文档为pdf，如果是word则设置为msword，excel为excel
    type: type || 'application/zip;charset=UTF-8',
  })
  // 创建a标签，利用download属性实现下载
  const a = document.createElement('a')
  // webkix兼容性处理
  const URL: any = window.URL || window.webkitURL
  // 根据解析后的blob对象创建URL对象即下载链接
  a.href = URL.createObjectURL(blob)
  a.download = filename || '压缩文件'
  document.body.appendChild(a)
  a.click()
  // 在dom中移除a标签
  document.body.removeChild(a)
  // 在内存中移除URL对象
  window.URL.revokeObjectURL(URL)
}

// 转换menudata数据
export function transformObject(node) {
  // let nodeParam: any = null
  // if (node.payload.nodeParam) {
  //   nodeParam = JSON.parse(node.payload.nodeParam)
  // }
  let nodeParam: any = null
  if (node.payload.nodeParam) {
    nodeParam = { isHide: 0 }
  }
  const transformedNode = {
    // path: node.payload.formLoadPath || '/',
    path: node.payload.nodeUrl || '/',
    name: node.nodeNo,
    id: node.payload.nodeId,
    meta: {
      // icon: node.payload.nodeImagePath,
      icon: node.payload.nodeImagePath,
      title: node.payload.nodeCname,
      isLink: '',
      isHide: nodeParam?.isHide,
      isFull: false,
      isAffix: nodeParam?.isAffix,
      isKeepAlive: true,
    },
    // children: null,
    component: node?.payload?.componentUrl,
  }

  if (node.subNodes) {
    transformedNode['children'] = node.subNodes.map((child) => transformObject(child))
  }
  if (node.payload?.nodeParam) {
    // let obj = node.payload?.nodeParam
    // obj = JSON.parse(obj)
    transformedNode.meta.isHide = 0
  }
  return transformedNode
}

// 菜单数据处理，type：0 添加icon属性，1：不添加icon 属性
export function initMenuData(data: any[], type = 0) {
  const arr: any[] = []
  Array.isArray(data) &&
    data.forEach((item) => {
      const temp: {
        id: string
        key: string
        icon?: any
        label: string
        title: string
        pathUrl?: string
        children: any[] | null
      } = {
        id: item.id,
        key: item.label,
        label: item.text,
        title: item.text,
        pathUrl: item.nodeUrl,
        children: item.children ? initMenuData(item.children, 1) : null,
        icon: type === 0 ? item.imagePath : '',
      }
      arr.push(temp)
    })
  return arr
}

export function formatTimeDuration(value) {
  const time = moment.duration(value, 'seconds') //得到一个对象，里面有对应的时分秒等时间对象值
  const hours = time.hours()
  const minutes = time.minutes()
  const seconds = time.seconds()
  return moment({ h: hours, m: minutes, s: seconds }).format('HH:mm:ss')
}
